<?php

namespace HuangYi\Rbac\Tests;

use HuangYi\Rbac\Models\Permission;
use HuangYi\Rbac\Models\RbacHelper;
use HuangYi\Rbac\Models\Role;
use HuangYi\Rbac\Tests\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Facade;
use Mockery as m;

trait MockTrait
{
    public static $id = 0;

    public function mockUser($name)
    {
        $user = new User;
        $user->name = $name;

        $permission1 = $this->mockRole('permission1');
        $permission2 = $this->mockRole('permission2');
        $permission3 = $this->mockRole('permission3');

        $role1 = $this->mockRole('role1', false);
        $role1->setRelation('permissions', new Collection([$permission1]));

        $role2 = $this->mockRole('role2', false);
        $role2->setRelation('permissions', new Collection([$permission2]));

        $role3 = $this->mockRole('role3', false);
        $role3->setRelation('permissions', new Collection([$permission3]));

        $user->setRelation('roles', Collection::make([$role1, $role2, $role3]));

        return $user;
    }

    protected function mockRole($name, $withPermissions = true)
    {
        $role = new Role;
        $role->id = $this->id();
        $role->name = $name;

        if ($withPermissions) {
            $role->setRelation('permissions', new Collection([
                $this->mockPermission('permission1'),
                $this->mockPermission('permission2'),
                $this->mockPermission('permission3'),
            ]));
        }

        return $role;
    }

    protected function mockPermission($name)
    {
        $permission = new Permission;
        $permission->id = $this->id();
        $permission->name = $name;

        return $permission;
    }

    protected function mockFacades()
    {
        $application = m::mock('app')->shouldReceive('instance')->getMock();
        Facade::setFacadeApplication($application);

        Config::swap(m::mock('config'));

        $defaults = require __DIR__ . '/../config/rbac.php';
        $this->mockDefaultConfig($defaults, 'rbac');
    }

    protected function mockDefaultConfig(array $items, $prefix)
    {
        foreach ($items as $key => $item) {
            if (is_int($key)) {
                break;
            }

            $name = $prefix . '.' . $key;

            Config::shouldReceive('get')->with($name)->andReturn($item)->byDefault();

            if (is_array($item)) {
                $this->mockDefaultConfig($item, $name);
            }
        }
    }

    protected function id()
    {
        static::$id++;

        return static::$id;
    }
}
